// ==================================================================
// contourBox.h
// contains all information relating to contours in program
// ==================================================================

#ifndef CONTOURBOX_H
#define CONTOURBOX_H

#include <algorithm>
#include <vector>
#include "vl/VLd.h"
#include "BoundingE.h"
#include <math.h>
#include <fstream>
#include <string>

class ContourBox;

//class representing a single contour
class Contour {
	public:
		Contour(ContourBox *boxPtr) {hullSet=transp=invis=ellipseSet=false;m_CBox=boxPtr;picked=false;modified=false;}
		//set of vertices describing contour
		std::vector<Vec2d> controlPts;
		std::vector<Vec3d> controlPts3f;

		//set of vertices describing convexHull of contour
		std::vector<Vec2d> convexHull;
		//color of contour
		Vec3d color;
		//defines best-fit ellipse
		BoundingE m_boundE;
		bool hullSet,ellipseSet;
		//are tilings invisible?
		bool invis;
		//are tilings transparent?
		bool transp;

		//list of contours connected to this contour in next plane
		std::vector<Vec2d> nextCont;
		
		//list of contours connected to this contour in previous plane
		std::vector<Vec2d> prevCont;
	
		//optimal tiling found by tiling algorithm between this contour and each member of the
		//prevCont set.
		std::vector< std::vector<Vec2d> > optimalPath;
		
		//list of vertices currently picked 
		std::vector<int> pickedNums;
		//is contour picked? 
		bool picked;
		//pointer to entire contourBox.
		ContourBox *m_CBox;
		//marks whether or not the mesh needs to be rebuilt
		bool modified;
		
		bool deleteVertices();
		bool pickPoint(Vec2d target,int &currPickV);		
		void setEllipse();
		void setHull();
		void addControlPt(Vec2d newPt);
		void addControlPt(Vec3d newPt);
		void optimizeTiling(int);
		void optimizeVertices();
		void insertPts(std::vector<Vec2d> &tmpPts);
		void pickBox(Vec2d boxStart,Vec2d boxCurr);
		void ComputeNormal(double n[3]);
		void ResetStartPoint();
};


//defines all contours at a single level 

class ContourPlane {
	public:
		//set of all contours on this plane
		std::vector<Contour> planeContours;
		void addContour(Contour newContour);
		void finishContour(int,bool);
		void modifyContour(int);
		void addPoint(int contourNum, Vec2d newPt);
		int getSize() {return planeContours.size(); }
		Vec3d getColor();
		void optimizeTiling(int,int);
		bool pickPoint(Vec2d target,int &currPickC, int &currPickV,bool);
};


//define all contours currently in existence
class ContourBox {
	public:
		//set of all image levels currently in existence
		std::vector<ContourPlane> contourSet;
		
		void pickContour(Vec2d);
		void updateCorresp(ContourPlane &plane1, ContourPlane &plane2,int plane1Num);
		void pickChain(Vec2d);
		void addBranch(Vec2d newB);
		void eraseBranch(Vec2d newB);
		void deselectAll();
		void deselectAll2d();
		void addPlane(ContourPlane newPlane);
		int getNumContours(int planeNum);
		void newContour(int planeNum, Contour newContour);
		void getLastPt(int currLevel,int numContours,Vec2d &prevPt);
		void deleteVertex(int currLevel,int currPickC,int currPickV);
		void finishContour(int , int, bool);
		void finishContourLoad(int , int);
		void cleanUpBranches(int,int);
		void newStrip(Vec2d,Vec2d);
		int deleteBoxVertices(int);
		void remesh();
		void saveModel(char *filename,float);
		void saveContour(float,char *);
		void addPoint(int planeNum, int contourNum, Vec2d newPt);
		std::vector<Vec2d> getControlPts(int,int);
		void eraseAll(int);
		Vec3d getPlaneColor(int planeNum);
		Contour *getContour(int planeNum,int contourNum);
		void pickPoint(int currLevel,Vec2d target,int &currPickC,int &currPickV,bool);
		void pickBox(int currLevel,Vec2d boxStart, Vec2d boxCurr);
		void modifyContour(int planeNum, int contourNum);
		void insertPts(std::vector<Vec2d> &tmpPts,int currLevel,int currC);
		Vec2d currScrollPos;
		void modifyPoint(int currLevel,Vec2d target,int currPickC,int currPickV);
		void modifyAllPoints(int currLevel,Vec2d target,int currPickC);
		void makeTrans();
		void makeInvis();
		void resetView();
};

#endif

